import { Callout, Tab, Tabs } from 'nextra/components';

# Deployment

Bref is designed out of the box to deploy using [the Serverless Framework](https://serverless.com/).

Bref can also work with any other deployment tool: Terraform, CloudFormation, SAM, [AWS CDK](https://github.com/brefphp/constructs), Pulumi… However, the documentation and user experience is optimized for Serverless Framework.

## Deploying manually

To deploy to AWS an application configured with `serverless.yml`, run:

<Tabs items={['Serverless CLI', 'Bref Cloud']}>
    <Tab>
        ```bash
        serverless deploy
        ```
    </Tab>
    <Tab>
        ```bash
        bref deploy
        ```
    </Tab>
</Tabs>

A `.serverless/` directory will be created. You can add it to `.gitignore`.

## Deploying for production

In the previous step, we deployed the project installed on your machine. This is probably a *development version*.

For production, we usually don't want to deploy:

- dev dependencies
- dev configuration
- etc.

Instead, let's remove development dependencies and optimize Composer's autoloader for production:

```bash
composer install --prefer-dist --optimize-autoloader --no-dev
```

<Callout>
    Using [aws/aws-sdk-php](https://github.com/aws/aws-sdk-php/tree/master/src/Script/Composer) or [google/apiclient](https://github.com/googleapis/google-api-php-client#cleaning-up-unused-services)? See the links for reducing deployment size by removing unused services
</Callout>

Now is also the best time to configure your project for production, as well as build any file cache if necessary.

Once your project is ready, you can deploy via the following command:

<Tabs items={['Serverless CLI', 'Bref Cloud']}>
    <Tab>
        ```bash
        serverless deploy
        ```
    </Tab>
    <Tab>
        ```bash
        bref deploy
        ```
    </Tab>
</Tabs>

## Environments

We can deploy the same application multiple times in completely separated environments (also called "stages" by the Serverless CLI).

<Tabs items={['Serverless CLI', 'Bref Cloud']}>
    <Tab>
        ```bash
        serverless deploy --stage=prod
        ```
    </Tab>
    <Tab>
        ```bash
        bref deploy --env=prod

        # or
        bref deploy -e prod
        ```
    </Tab>
</Tabs>

The default environment is `dev`. The example above deploys a `prod` environment.

Each environment is a separate CloudFormation stack, with completely separate AWS resources (Lambda functions, logs, permissions, etc.). All AWS resources are prefixed with the `service` and environment name (for example `myapp-dev-api`), which avoids any collision between environments.

It is possible to deploy different environments in different AWS accounts (to lock down permissions), and to deploy one environment per git branch, pull request, or even developer in the team.

## Automating deployments

### Bref Cloud

If you are using [Bref Cloud](https://bref.sh/cloud), you can easily set up automatic deployments from CI/CD tools.

Read the [documentation on deploying with Bref Cloud](./cloud-deploy.mdx) for more information.

### Serverless CLI

If you are using GitHub Actions, Gitlab CI, CircleCI, or any tool of the sort you will want to automate the deployment to something like this:

```bash
# Install Composer dependencies optimized for production
composer install --prefer-dist --optimize-autoloader --no-dev

# Perform extra tasks for your framework of choice
# (e.g. generate the framework cache)
# [...]

# Deploy
serverless deploy
```

That will also mean creating AWS access keys so that the continuous integration is allowed to deploy.

You can find configuration examples for CI/CD tools in the [Bref examples repository](https://github.com/brefphp/examples).

## Regions

AWS runs applications in different [regions](https://aws.amazon.com/about-aws/global-infrastructure/). The default region is `us-east-1` (North Virginia, USA).

If you want to use a different region (for example to host your application closer to your visitors) you can configure it in your `serverless.yml`:

```yaml
provider:
    region: eu-west-1 # Ireland, Europe
    ...
```

<Callout>
    If you are a first time user, using the `us-east-1` region (the default region) is recommended for the first projects. It simplifies commands and avoids a lot of mistakes when discovering AWS.
</Callout>

## Deletion

You can delete a deployed environment using the `remove` command.

<Tabs items={['Serverless CLI', 'Bref Cloud']}>
    <Tab>
        ```bash
        serverless remove

        # or remove a specific environment
        serverless remove --stage=prod
        ```

        Note that because of the way Serverless Framework works, you will need to delete the contents of AWS S3 buckets manually before running this command.
    </Tab>
    <Tab>
        ```bash
        bref remove

        # or remove a specific environment
        bref remove --env=prod
        ```

        Bref Cloud will automatically delete the contents of AWS S3 buckets.
    </Tab>
</Tabs>

**Deleting an environment destroys the AWS resources that were created for that environment.**

If you want to delete all environments of an application, you can do so in the [Bref Cloud dashboard](https://bref.cloud). If you don't use Bref Cloud, you will need to delete each environment one by one.

## How it works

### CloudFormation stacks

Under the hood, Bref will deploy everything to AWS as a **[CloudFormation](https://aws.amazon.com/cloudformation/) stack**. A "stack" is nothing more than a bunch of things that compose an application:

- Lambda functions
- HTTP endpoints
- S3 buckets
- databases
- etc.

Stacks make it easy to group those resources together: the whole stack is updated at once on deployments, and if you delete the stack all the resources inside are deleted together too. Clean and simple.

### Zero-downtime deployments

CloudFormation deploys using the [blue/green deployment strategy](https://docs.aws.amazon.com/whitepapers/latest/overview-deployment-options/bluegreen-deployments.html).

This means that when you deploy, a new version of your code is deployed alongside the old one. Once the new version is ready, the traffic switches to the new version. If the deployment fails at any point, the traffic stays on the old version and the deployment is rolled back.

#### Limits to blue/green deployment

As soon as you introduce **asynchronous behaviors** (e.g. background jobs with SQS, event-driven microservices…) you may have in-flight messages (SQS jobs, EventBridge events…) created by the old version of your code that will be processed by the new version of your code.

Code that handles asynchronous events must be able to handle messages created by older versions of the code.

#### Database migrations

Zero-downtime deployments mean that database migrations must run when code is running in production. That means either before or after the deployment (traffic switch) happens, and having a DB migration strategy compatible with that.

### `serverless.yml`

Serverless Framework offers a simple configuration format. This is what you are using if you use Bref. That configuration is written in your project in a `serverless.yml` file.

You can [learn more about that configuration format here](environment/serverless-yml.md).

## Learn more

Read more about `serverless deploy` in [the official documentation](https://github.com/oss-serverless/serverless/blob/main/docs/guides/deploying.md).
